import {Injectable} from '@angular/core';
import {DirectoryCapacity, FileDesc, FileDetails} from "../model/file-view";
import {map, Observable, Subject} from "rxjs";
import {HttpClient} from "@angular/common/http";
import {HttpService} from "./http.service";
import {Result} from "../model/restful";
import {NzProgressStatusType} from "ng-zorro-antd/progress/typings";

enum SortStrategy {
  SIZE, A_Z, Z_A, LATEST, OLDEST
}

@Injectable({
  providedIn: 'root'
})
export class FileViewService {

  private multipleChoice = false

  multipleChoiceSubject = new Subject<boolean>()

  type2icon = new Map<string, string>()

  constructor(private server: HttpService, private httpClient: HttpClient) {
    this.initIconMap()
  }

  displayFiles(path: string): Observable<FileDesc[]> {
    return this.loadFilesFromServer(path).pipe(
      map((r) => {
        if (r.data === null) {
          return []
        } else {
          return r.data.map(file => this.fileResolve(file))
        }
      })
    )
  }

  humanReadable(size: number | undefined): string {
    if (size == undefined)
      return '0 B'
    const b = 1
    const k = b * 1024
    const m = k * 1024
    const g = m * 1024
    let value = ''
    if (size > g) {
      const gCount = FileViewService.filesizeReduce(size / g)
      value = `${gCount} GB`
    } else if (size > m) {
      const mCount = FileViewService.filesizeReduce(size / m)
      value = `${mCount} MB`
    } else if (size > k) {
      const kCount = FileViewService.filesizeReduce(size / k)
      value = `${kCount} KB`
    } else {
      value = `${size} B`
    }
    return value
  }

  private static filesizeReduce(num: number): string {
    if (Number.isInteger(num)) return num.toString()
    else return num.toFixed(2)
  }

  sortFiles(
    files: FileDesc[],
    strategy: SortStrategy = SortStrategy.A_Z
  ): FileDesc[] {
    return files
  }

  toggleMultipleChoice() {
    this.multipleChoice = !this.multipleChoice
    this.multipleChoiceSubject.next(this.multipleChoice)
  }

  loadFilesFromServer(path: string): Observable<Result<FileDesc[]>> {
    return this.httpClient.get<Result<FileDesc[]>>(this.server.baseUrl() + `/file/list?path=${path}`)
  }

  displayFileDetails(desc: FileDesc): Observable<FileDetails> {
    let filepath: string = ''
    if (desc.path == '') {
      filepath = desc.path + '/' + desc.filename
    } else {
      filepath = desc.filename
    }

    return this.httpClient.get<FileDetails>(this.server.baseUrl() + '/file/info?path=' + filepath)
  }

  displayServerStorageSpace(): Observable<Result<DirectoryCapacity>> {
    return this.httpClient.get<Result<DirectoryCapacity>>(this.server.baseUrl() + '/file/cap?path=/')
  }

  storageStage(num: number): NzProgressStatusType {
    if (num < 50) return 'success'
    if (num < 70) return 'normal'
    if (num < 85) return 'active'
    else return 'exception'
  }

  fileResolve(file: FileDesc): FileDesc {
    file.checked = false
    file.selected = false
    file.disabled = false
    if (this.isDirectory(file)) {
      file.priority = 5
    } else {
      file.priority = 1
    }

    if (this.type2icon.has(file.filetype)) {
      file.icon = this.type2icon.get(file.filetype)!
    } else {
      file.icon = this.type2icon.get('unknown')!
    }
    return file
  }

  public getFileIcon(filename: string): string {
    const pointerIdx = filename.lastIndexOf('.')
    if (pointerIdx < 0 || pointerIdx == filename.length - 1)
      return this.type2icon.get('unknown')!!
    const filetype = filename.substring(pointerIdx + 1)

    if (this.type2icon.has(filetype)) {
      return this.type2icon.get(filetype)!!
    } else {
      return this.type2icon.get('unknown')!!
    }
  }

  private initIconMap() {
    // 文件夹
    this.type2icon.set('dir', 'icon-wenjianleixing-biaozhuntu-wenjianjia')
    this.type2icon.set('directory', 'icon-wenjianleixing-biaozhuntu-wenjianjia')
    this.type2icon.set('folder', 'icon-wenjianleixing-biaozhuntu-wenjianjia')

    // 未知文件
    this.type2icon.set('unknown', 'icon-wenjianleixing-biaozhuntu-weizhiwenjian')

    // 链接文件
    this.type2icon.set('link', 'icon-wenjianleixing-biaozhuntu-lianjie')

    // 压缩文件
    this.type2icon.set('zip', 'icon-wenjianleixing-biaozhuntu-yasuowenjian')
    this.type2icon.set('rar', 'icon-wenjianleixing-biaozhuntu-yasuowenjian')
    this.type2icon.set('gz', 'icon-wenjianleixing-biaozhuntu-yasuowenjian')
    this.type2icon.set('7z', 'icon-wenjianleixing-biaozhuntu-yasuowenjian')
    this.type2icon.set('z', 'icon-wenjianleixing-biaozhuntu-yasuowenjian')

    // 文本文件
    this.type2icon.set('txt', 'icon-wenjianleixing-biaozhuntu-jishiben')

    // word文件
    this.type2icon.set('doc', 'icon-wenjianleixing-biaozhuntu-Wordwendang')
    this.type2icon.set('docx', 'icon-wenjianleixing-biaozhuntu-Wordwendang')
    this.type2icon.set('wps', 'icon-wenjianleixing-biaozhuntu-Wordwendang')

    // excel文件
    this.type2icon.set('xls', 'icon-wenjianleixing-biaozhuntu-Wordwendang')
    this.type2icon.set('xlsx', 'icon-wenjianleixing-biaozhuntu-Wordwendang')

    // ppt文件
    this.type2icon.set('ppt', 'icon-wenjianleixing-biaozhuntu-huandengpian')

    // pdf
    this.type2icon.set('pdf', 'icon-wenjianleixing-biaozhuntu-PDFwendang')

    // 图片文件
    this.type2icon.set('bmp', 'icon-wenjianleixing-biaozhuntu-tupianwenjian')
    this.type2icon.set('gif', 'icon-wenjianleixing-biaozhuntu-tupianwenjian')
    this.type2icon.set('jpg', 'icon-wenjianleixing-biaozhuntu-tupianwenjian')
    this.type2icon.set('png', 'icon-wenjianleixing-biaozhuntu-tupianwenjian')

    // 视频文件
    this.type2icon.set('mp4', 'icon-wenjianleixing-biaozhuntu-shipinwenjian')
    this.type2icon.set('wmv', 'icon-wenjianleixing-biaozhuntu-shipinwenjian')
    this.type2icon.set('asf', 'icon-wenjianleixing-biaozhuntu-shipinwenjian')
    this.type2icon.set('rm', 'icon-wenjianleixing-biaozhuntu-shipinwenjian')
    this.type2icon.set('rmvb', 'icon-wenjianleixing-biaozhuntu-shipinwenjian')
    this.type2icon.set('mov', 'icon-wenjianleixing-biaozhuntu-shipinwenjian')
    this.type2icon.set('flv', 'icon-wenjianleixing-biaozhuntu-shipinwenjian')
    this.type2icon.set('avi', 'icon-wenjianleixing-biaozhuntu-shipinwenjian')

    // 音频文件
    this.type2icon.set('wav', 'icon-wenjianleixing-biaozhuntu-shengyinwenjian')
    this.type2icon.set('mp3', 'icon-wenjianleixing-biaozhuntu-shengyinwenjian')
  }

  isOpenable(file: FileDesc): boolean {
    const type = file.filetype
    return type === 'txt' || type === 'md' || type === 'pdf' || type === 'jpg' ||
      type === 'mp3' || type === 'mp4'
  }

  isZipFile(file: FileDesc): boolean {
    const type = file.filetype
    return type == 'zip' || type == 'gzip'
  }

  isEditable(file: FileDesc | undefined): boolean {
    if (file === undefined) return false
    return file.filetype === 'txt'
  }

  isDirectory(file: FileDesc): boolean {
    const type = file.filetype
    return type === 'dir' || type === 'link' || type === 'directory'
      || type === 'folder'
  }

  private static fileIdentifies(file: FileDesc): string {
    return `${file.path}:${file.filename}`
  }
}
